﻿/*
 * DATAFLOWCORE
 * 
Copyright 2012 - Mindstorm Multitouch Limited

Author - Bertrand Nouvel

DataFlowCore is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

DataFlowCore is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU Lesser Public License for more details.
*/


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MongoDB.Bson;

namespace DFlow
{
    /// <summary>
    /// Modules are global event handlers with parameters
    /// that can be activated in the vogon engine.
    /// </summary>
    public class Module : IDisposable
    {

        #region AUTO_REGISTER_PLUGIN_TYPE
        static private List<System.Type> _AllModuleTypes = null;

        static private void RecomputeAllModuleTypes()
        {
            _AllModuleTypes = new List<System.Type>();
            foreach (System.Reflection.Assembly a in AppDomain.CurrentDomain.GetAssemblies())
            {
                try
                {
                    foreach (System.Type t in a.GetExportedTypes())
                    {
                        if (t.IsSubclassOf(typeof(Module)))
                        {
                            if (!_AllModuleTypes.Contains(t))
                            {
                                _AllModuleTypes.Add(t);
                            }
                        }
                    }
                }
                catch (System.NotSupportedException) { }
            }
        }
        static public List<System.Type> AllModuleTypes
        {
            get
            {
                if (_AllModuleTypes == null)
                {
                    AppDomain.CurrentDomain.AssemblyLoad += (e, x) => { RecomputeAllModuleTypes(); };
                    RecomputeAllModuleTypes();
                }
                return _AllModuleTypes;
            }
        }

        #endregion

        object parameters;


        static List<Module> _Instances = new List<Module>();
        public static IEnumerable<Module> Instances { get { return _Instances; } }

        public Module() { _Instances.Add(this); }
        ~Module() { _Instances.Remove(this); }



        public virtual object DefaultParameters()
        {
            return this.GetType().GetNestedType("Parameters").InvokeMember(null, System.Reflection.BindingFlags.CreateInstance, null, null, null);
        }

        public object GetParameters()
        {
            if (parameters == null)
            {
                parameters = DefaultParameters();
            }
            return parameters;
        }

        public virtual void UpdateParameters(BsonDocument doc)
        {
            if (parameters == null) { parameters = DefaultParameters(); }
            DFlowCore.BsonUtils.UpdateObject(parameters, doc);
        }

        protected DFlowCore.Engine host_engine = null;
        protected object[] arguments = null;

        public virtual void Initialize(DFlowCore.Engine engine, object[] args) { host_engine = engine; arguments = args; }
        public virtual void Dispose() { }

        public virtual void Start() { }
        public virtual void Stop() { }

        public virtual void OnNewDataflow(DFlow.Dataflow p) { }
        public virtual void OnDeleteDataflow(DFlow.Dataflow p) { }

        public virtual void OnProcess() { }

        public static void InstancesRemoveAll(Predicate<DFlow.Module> p)
        {
            foreach (DFlow.Module cm in Instances.Where(x => p(x)))
            {
                cm.Dispose();
            }
            _Instances.RemoveAll(p);
        }

    }
}
